<?php


namespace EasySwoole\EasySwoole;


use App\Crontab\CustomCrontab;
use App\Tools\Session;
use EasySwoole\EasySwoole\AbstractInterface\Event;
use EasySwoole\EasySwoole\Crontab\Crontab;
use EasySwoole\EasySwoole\Swoole\EventRegister;
use EasySwoole\ORM\Db\Connection;
use EasySwoole\ORM\DbManager;
use EasySwoole\Session\FileSession;

class EasySwooleEvent implements Event
{
    public static function initialize()
    {
        # 时区设置
        date_default_timezone_set('Asia/Shanghai');

        # MySQL的数据库配置
        $config = new \EasySwoole\ORM\Db\Config(Config::getInstance()->getConf("MYSQL"));
        DbManager::getInstance()->addConnection(new Connection($config));


    }


    public static function mainServerCreate(EventRegister $register)
    {
        # 注册session
        // 基于文件存储，传入 EASYSWOOLE_TEMP_DIR . '/Session' 目录作为session的数据存储位置
        Session::getInstance(new FileSession(EASYSWOOLE_TEMP_DIR . '/Session'));

        # 注册crontab
        Crontab::getInstance()->addTask(CustomCrontab::class);

        ## 自定义进程
        $processConfig = new \EasySwoole\Component\Process\Config([
            'processName'     => 'CustomProcess', // 设置 进程名称为 TickProcess
            'processGroup'    => 'Custom', // 设置 进程组名称为 Tick
            'arg'             => [
                'arg1' => 'this is arg1!',
            ], // 传递参数到自定义进程中
            'enableCoroutine' => true, // 设置 自定义进程自动开启协程环境
        ]);

        // 【推荐】使用 \EasySwoole\Component\Process\Manager 类注册自定义进程
        $customProcess = (new \App\Process\CustomProcess($processConfig));
        // 【可选操作】把 tickProcess 的 Swoole\Process 注入到 Di 中，方便在后续控制器等业务中给自定义进程传输信息(即实现主进程与自定义进程间通信)
        \EasySwoole\Component\Di::getInstance()->set('customSwooleProcess', $customProcess->getProcess());
        // 注册进程
        \EasySwoole\Component\Process\Manager::getInstance()->addProcess($customProcess);


        ## todo 异步任务，同步为啥不执行
        // 同步
        \EasySwoole\EasySwoole\Task\TaskManager::getInstance()->sync(function () {
            echo 'sync';

            // 打印和记录 `INFO` 等级、`info` 分类的日志
            \EasySwoole\EasySwoole\Logger::getInstance()->log('sync',
                \EasySwoole\Log\LoggerInterface::LOG_LEVEL_INFO,'info');

        });

        // 异步
        \EasySwoole\EasySwoole\Task\TaskManager::getInstance()->async(function () {
            echo 'async';
            // 打印和记录 `INFO` 等级、`info` 分类的日志
            \EasySwoole\EasySwoole\Logger::getInstance()->log('async',
                \EasySwoole\Log\LoggerInterface::LOG_LEVEL_INFO,'info');
        }, function ($reply, $taskId, $workerIndex) {
            // $reply 返回的执行结果
            // $taskId 任务id
            echo 'async success';
        });


        // 打印和记录 `INFO` 等级、`info` 分类的日志
        \EasySwoole\EasySwoole\Logger::getInstance()->log('record level:INFO-category:info log info',\EasySwoole\Log\LoggerInterface::LOG_LEVEL_INFO,'info');


        ### 通常出现重大异常（支付失败等）需要进行报警处理，在全局的mainServerCreate事件中进行注册 ###
        \EasySwoole\EasySwoole\Trigger::getInstance()->onException()->set('notify', function (\Throwable $throwable) {
            // 自行实现通知代码
            echo "onException: 回调接管注册\n";
        });

        \EasySwoole\EasySwoole\Trigger::getInstance()->onError()->set('notify', function ($msg) {
            // 自行实现通知代码
            echo "onError: 回调接管注册\n";
        });


        # 经典案例-订单状态超时监控
        $register->add(EventRegister::onWorkerStart, function (\swoole_server $server, $workerId) {
            //如何避免定时器因为进程重启而丢失
            //例如在第一个进程 添加一个10秒的定时器
            if ($workerId == 0) {
                \EasySwoole\Component\Timer::getInstance()->loop(10 * 1000, function () {
                    // 从数据库，或者是redis中，去获取下个就近10秒内需要执行的任务
                    // 例如:2秒后一个任务，3秒后一个任务 代码如下
                    \EasySwoole\Component\Timer::getInstance()->after(2 * 1000, function () {
                        //为了防止因为任务阻塞，引起定时器不准确，把任务给异步进程处理
                        // Logger::getInstance()->console("time 2", false);
                    });
                    \EasySwoole\Component\Timer::getInstance()->after(3 * 1000, function () {
                        //为了防止因为任务阻塞，引起定时器不准确，把任务给异步进程处理
                        // Logger::getInstance()->console("time 3", false);
                    });
                });
            }
        });


        // 每隔 10 秒执行一次
        $timeId1 = \EasySwoole\Component\Timer::getInstance()->loop(10 * 1000, function () {
            // echo "this timer runs at intervals of 10 seconds\n";
        });

        // 10 秒后执行一次
        $timeId2 = \EasySwoole\Component\Timer::getInstance()->after(10 * 1000, function () {
            // echo "ten seconds later， 延迟任务，只执行一次\n";
        });

        // 清除该定时器
        // var_dump(\EasySwoole\Component\Timer::getInstance()->clear($timeId1)); // bool(true)
        // var_dump($timeId1, $timeId2); // int(1)

        // 定时器得不到执行 不输出：timeout


    }
}
